
package com.oahcfly.chgame.egret.ui;

import java.lang.reflect.Field;
import java.util.HashMap;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.Action;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.Touchable;
import com.badlogic.gdx.scenes.scene2d.ui.Button;
import com.badlogic.gdx.scenes.scene2d.ui.Button.ButtonStyle;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.Scaling;
import com.oahcfly.chgame.core.Chao;
import com.oahcfly.chgame.core.annotations.ExmlBaseSkinUIAnnotation;
import com.oahcfly.chgame.core.freefont.FreeFont;
import com.oahcfly.chgame.core.helper.CHFontHelper;
import com.oahcfly.chgame.core.listener.CHClickListener;
import com.oahcfly.chgame.core.listener.CHClickListener.CLICKTYPE;
import com.oahcfly.chgame.core.mvc.CHModel;
import com.oahcfly.chgame.core.mvc.CHScreen;
import com.oahcfly.chgame.egret.Egret;
import com.oahcfly.chgame.egret.ui.actor.BitmapLabel;
import com.oahcfly.chgame.egret.ui.property.BaseUIProperty;
import com.oahcfly.chgame.egret.ui.property.BitmapLabelProperty;
import com.oahcfly.chgame.egret.ui.property.ButtonProperty;
import com.oahcfly.chgame.egret.ui.property.GroupProperty;
import com.oahcfly.chgame.egret.ui.property.LabelProperty;
import com.oahcfly.chgame.egret.ui.property.PanelProperty;
import com.oahcfly.chgame.egret.ui.property.UIAssetProperty;
import com.oahcfly.chgame.util.CHLog;

/** 基础的UI皮肤类《图片,按钮,数字图片,文本...》 ->变量必须使用public属性，才能被预加载赋值。
 * 
 * @author haocao */
public abstract class EXMLBaseSkinUI extends Group {
	private String cmdName;

	/** 获取注解 */
	public ExmlBaseSkinUIAnnotation getAnnotation () {
		if (this.getClass().isAnnotationPresent(ExmlBaseSkinUIAnnotation.class)) {
			// 若存在就获取注解
			ExmlBaseSkinUIAnnotation annotation = (ExmlBaseSkinUIAnnotation)this.getClass().getAnnotation(
				ExmlBaseSkinUIAnnotation.class);
			return annotation;
		} else {
			return null;
		}
	}

	public EXMLBaseSkinUI (String cmdName) {
		ExmlBaseSkinUIAnnotation annotation = getAnnotation();
		if (annotation == null) {
			throw new GdxRuntimeException("找不到ExmlBaseSkinUIAnnotation，确保在类名上方添加了注解。");
		}
		String exmlPath = annotation.exmlPath();
		String resPath = annotation.resPath();

		this.cmdName = cmdName;
		init(Egret.loadExmlProperty(exmlPath), resPath);
	}

	public EXMLBaseSkinUI (String exmlPath, String resPath, String cmdName) {
		this(exmlPath, resPath);
		this.cmdName = cmdName;
	}

	public EXMLBaseSkinUI (String exmlPath, String resPath) {
		init(Egret.loadExmlProperty(exmlPath), resPath);
	}

	private void init (Array<BaseUIProperty> propertys, String resPath) {
		Egret.autoLoadRes(resPath);

		for (BaseUIProperty baseUIProperty : propertys) {
			if (baseUIProperty instanceof PanelProperty) {
				// 面板
				Group group = new Group();
				parseBaseProperty(group, baseUIProperty);
				this.addActor(group);
			} else if (baseUIProperty instanceof GroupProperty) {
				parseBaseProperty(this, baseUIProperty);
			} else if (baseUIProperty instanceof UIAssetProperty) {
				Image actor = new Image();
				parseUIAssetProperty(actor, (UIAssetProperty)baseUIProperty);
				parseBaseProperty(actor, baseUIProperty);
				this.addActor(actor);
			} else if (baseUIProperty instanceof ButtonProperty) {
				Button actor = new Button();
				parseButtonProperty(actor, (ButtonProperty)baseUIProperty);
				parseBaseProperty(actor, baseUIProperty);
				this.addActor(actor);
			} else if (baseUIProperty instanceof BitmapLabelProperty) {
				String path = ERes.getResUrl(((BitmapLabelProperty)baseUIProperty).fntName);
				if (path == null) {
					Gdx.app.error(getClass().getSimpleName(), "path is null,error :" + ((BitmapLabelProperty)baseUIProperty).fntName);
				}
				FileHandle fileHandle = Gdx.files.internal(path);
				String dataString = fileHandle.readString();
				if (dataString.contains("info")) {
					//
					BitmapFont bitmapFont = CHFontHelper.getInstance().loadFntFont(path);
					Label label = new Label(((BitmapLabelProperty)baseUIProperty).text, new LabelStyle(bitmapFont, null));
					parseBaseProperty(label, baseUIProperty);
					this.addActor(label);
				} else {
					// egret生成fnt文件
					FntParser fntParser = new FntParser(path);
					BitmapLabel bitmapLabel = new BitmapLabel(fntParser);
					parseBitmalLabelProperty(bitmapLabel, (BitmapLabelProperty)baseUIProperty);
					parseBaseProperty(bitmapLabel, baseUIProperty);
					this.addActor(bitmapLabel);
				}
			} else if (baseUIProperty instanceof LabelProperty) {
				BitmapFont bitmapFont = FreeFont.getBitmapFont().appendText(((LabelProperty)baseUIProperty).text);
				Color color = Color.valueOf(((LabelProperty)baseUIProperty).textColor);
				Label label0 = new Label(((LabelProperty)baseUIProperty).text, new LabelStyle(bitmapFont, color));
				label0.setWrap(true);
				parseLabelProperty(label0, (LabelProperty)baseUIProperty);
				parseBaseProperty(label0, baseUIProperty);
				this.addActor(label0);
			}
		}

		doInit();
	}

	/** 自动获取当前变量名称，并且给变量赋值 */
	private void doInit () {
		// 获取变量名称
		try {
			Field[] fields = this.getClass().getFields();
			for (Field field : fields) {
				field.set(this, findActor(field.getName()));
			}
		} catch (IllegalArgumentException e) {
			CHLog.error("变量赋值失败：" + e.getLocalizedMessage());
		} catch (IllegalAccessException e) {
			CHLog.error("变量赋值失败：" + e.getLocalizedMessage());
		}
	}

	private void parseLabelProperty (Label label, LabelProperty labelUIProperty) {
		String align = labelUIProperty.textAlign;
		// 文字垂直方向：verticalAlign ： top middle bottom
		// 文字水平方向：textAlign： left middle right

		int gdxAlign_1 = Integer.MAX_VALUE;
		int gdxAlign_2 = Integer.MAX_VALUE;
		if ("left".equals(align)) {
			gdxAlign_1 = Align.left;
		} else if ("middle".equals(align)) {
			gdxAlign_1 = Align.center;
		} else if ("right".equals(align)) {
			gdxAlign_1 = Align.right;
		}

		align = labelUIProperty.verticalAlign;
		if ("top".equals(align)) {
			gdxAlign_2 = Align.top;
		} else if ("middle".equals(align)) {
			gdxAlign_2 = Align.center;
		} else if ("bottom".equals(align)) {
			gdxAlign_2 = Align.bottom;
		}

		if (gdxAlign_1 < Integer.MAX_VALUE && gdxAlign_1 < Integer.MAX_VALUE) {
			label.setAlignment(gdxAlign_1 | gdxAlign_2);
		} else if (gdxAlign_1 < Integer.MAX_VALUE) {
			label.setAlignment(gdxAlign_1);
		} else if (gdxAlign_2 < Integer.MAX_VALUE) {
			label.setAlignment(gdxAlign_2);
		}
	}

	private void parseBaseProperty (Actor actor, BaseUIProperty baseUIProperty) {

		// 是否可点击
		actor.setTouchable(baseUIProperty._touchEnabled ? Touchable.enabled : Touchable.disabled);

		// 锚点默认中心
		actor.setOrigin(Align.center);

		// 名称
		if (baseUIProperty._id != null) {
			actor.setName(baseUIProperty._id);
		}

		float width = baseUIProperty._width;
		float height = baseUIProperty._height;
		// 宽 高
		// 距离四个边缘的距离[优先级大于宽高设定]
		boolean layout = width > 0 || height > 0;
		if (baseUIProperty._left != -1) {
			width -= baseUIProperty._left;
			layout = true;
		}

		if (baseUIProperty._right != -1 && baseUIProperty._left != -1) {
			width = Chao.gameW;
		}

		if (baseUIProperty._top != -1 && baseUIProperty._bottom != -1) {
			height = Chao.gameH;
		}

		if (baseUIProperty._right != -1) {
			width -= baseUIProperty._right;
			layout = true;
		}

		if (baseUIProperty._left != -1) {
			width -= baseUIProperty._left;
			layout = true;
		}

		if (baseUIProperty._top != -1) {
			height -= baseUIProperty._top;
			layout = true;
		}

		if (baseUIProperty._bottom != -1) {
			layout = true;
			height -= baseUIProperty._bottom;
		}

		if (layout) {
			actor.setSize(width, height);
		}

		// 坐标转换，egret以左上角，libgdx以左下角
		float x = baseUIProperty._x;
		float y = Chao.gameH - baseUIProperty._y - actor.getHeight();
		if (baseUIProperty._left != -1) {
			x += baseUIProperty._left;
		}
		if (baseUIProperty._top != -1) {
			y -= baseUIProperty._top;
		}

		// 坐标
		actor.setPosition(x, y);

		// 垂直居中
		if (baseUIProperty._verticalCenter != -1) {
			actor.setY(Chao.gameH / 2 - actor.getHeight() / 2 - baseUIProperty._verticalCenter);
		}
		// 水平居中
		if (baseUIProperty._horizontalCenter != -1) {
			actor.setX(Chao.gameW / 2 - actor.getWidth() / 2 + baseUIProperty._horizontalCenter);
		}

		// 缩放
		actor.setScale(baseUIProperty._scaleX, baseUIProperty._scaleY);
		if (actor instanceof Label) {
			((Label)actor).setFontScale(baseUIProperty._scaleX, baseUIProperty._scaleY);
		}

		// 可见性
		actor.setVisible(baseUIProperty._visible);
	}

	private void parseUIAssetProperty (Image actor, UIAssetProperty uiAssetProperty) {
		Texture texture = ERes.getResTexture(uiAssetProperty.source);
		actor.setDrawable(new TextureRegionDrawable(new TextureRegion(texture)));
		actor.setScaling(Scaling.stretch);
		actor.setAlign(Align.center);
		actor.setSize(actor.getPrefWidth(), actor.getPrefHeight());
	}

	private void parseButtonProperty (Button button, ButtonProperty buttonProperty) {
		Texture upTexture = ERes.getResTexture(buttonProperty.upSource);
		Texture downTexture = ERes.getResTexture(buttonProperty.downSource);
		TextureRegionDrawable up = new TextureRegionDrawable(new TextureRegion(upTexture));
		TextureRegionDrawable down = new TextureRegionDrawable(new TextureRegion(downTexture));

		button.setStyle(new ButtonStyle(up, down, up));
		button.setSize(button.getPrefWidth(), button.getPrefHeight());
	}

	private void parseBitmalLabelProperty (BitmapLabel bitmapLabel, BitmapLabelProperty bitmapLabelProperty) {
		bitmapLabel.setText(bitmapLabelProperty.text);
	}

	/** 创建子元素完毕 */
	public abstract void createChildComplete ();

	/** 注册监听器
	 * 
	 * @param chClickListener */
	public abstract void addClickListener (CHClickListener chClickListener);

	/** 组件被点击中
	 * 
	 * @param actor */
	public abstract void uiClicked (Actor actor);

	public CHScreen getScreen () {
		return Chao.game.getScreen();
	}

	private boolean inited = false;
	private CLICKTYPE clickType = CLICKTYPE.SCALE;

	public CLICKTYPE getClickType () {
		return clickType;
	}

	public void setClickType (CLICKTYPE clickType) {
		this.clickType = clickType;
	}

	private void initUI () {
		inited = true;
		this.createChildComplete();

		CHClickListener chClickListener = new CHClickListener(clickType) {

			@Override
			public void doClicked (InputEvent event, float x, float y) {
				uiClicked(event.getListenerActor());
			}
		};

		this.addClickListener(chClickListener);
	}

	@Override
	protected void setStage (Stage stage) {
		if (stage != null && !inited) {
			initUI();
		}
		super.setStage(stage);
	}

	public void show () {
		getScreen().showSkinUI(this);
	}

	public void show (Action action) {
		getScreen().showSkinUI(this, action);
	}

	public void disimiss () {
		getScreen().dismissSkinUI(this);
	}

	public String getCMDName () {
		return cmdName;
	}

	public void setCMDName (String cmdName) {
		this.cmdName = cmdName;
	}

	public <T extends CHModel> T getModel () {
		return getScreen().getModel();
	}

	/** 接收更新UI通知
	 * @param data */
	public abstract void handleUIEvent (HashMap<String, String> data);
}
